﻿using PloobsEngine.SceneControl;
using PloobsEngine.Physics;
using PloobsEngine;
using PloobsEngine.Cameras;
using PloobsEngine.Input;
using Microsoft.Xna.Framework;
using PloobsEngine.Physics.Bepu;
using PloobsEngine.Modelo;
using PloobsEngine.Material;
using Microsoft.Xna.Framework.Graphics;
using PloobsEngine.Features;
using PloobsEngine.Commands;
using PloobsEngineDemo3;
using PloobsEngine.Light;
using Microsoft.Xna.Framework.Input;
using PloobsEngine.Draw;

namespace Etapa1.Screens
{    
    /// <summary>
    /// InputScreen
    /// </summary>
    public class InputScreen: SceneScreen
    {
        private BepuPhysicWorld physicWorld;
        private BrutalForceWorld mundo;
        private EngineStuff engine;        
        ICamera cam;

        public InputScreen(EngineStuff es)
        {
            this.engine = es;
            physicWorld = new BepuPhysicWorld();
            mundo = new BrutalForceWorld(physicWorld);                                    
        }

        
        public override void LoadContent(EngineStuff es)
        {
            ///MUST BE ADDED TO USE THE INPUT COMPONENT
            InputAdvanced inp = new InputAdvanced(engine);
            engine.AddComponent(inp);

            base.LoadContent(es);

            #region Models

            {
                SimpleModel sm = new SimpleModel("..\\Content\\Model\\cenario");
                sm.LoadModelo();
                IPhysicObject pi = new TriangleMeshObject(Vector3.Zero, sm);
                CustomDeferred shader = new CustomDeferred(false, false, false, false);
                shader.SpecularIntensity = 0;
                shader.SpecularPower = 0;
                shader.Initialize();
                IMaterial mat = new Material(shader);
                IObject obj3 = new SimpleObject(mat, pi, sm);
                mundo.AddObject(obj3);
            }


            #endregion

            cam = new CameraFirstPerson(true);
            cam.FarPlane = 3000;

            LightThrowBepu lt = new LightThrowBepu(mundo, engine);

            #region NormalLight
            DirectionalLight ld1 = new DirectionalLight(Vector3.Left, Color.White);
            DirectionalLight ld2 = new DirectionalLight(Vector3.Right, Color.White);
            DirectionalLight ld3 = new DirectionalLight(Vector3.Backward, Color.White);
            DirectionalLight ld4 = new DirectionalLight(Vector3.Forward, Color.White);
            DirectionalLight ld5 = new DirectionalLight(Vector3.Down, Color.White);
            float li = 0.4f;
            ld1.LightIntensity = li;
            ld2.LightIntensity = li;
            ld3.LightIntensity = li;
            ld4.LightIntensity = li;
            ld5.LightIntensity = li;
            mundo.AddLight(ld1);
            mundo.AddLight(ld2);
            mundo.AddLight(ld3);
            mundo.AddLight(ld4);
            mundo.AddLight(ld5);
            #endregion

            ////Criacao de uma Tecnica
            DeferredRenderTechnic dr = new DeferredRenderTechnic(engine);

            IRenderTechnic[] rt = new IRenderTechnic[] { dr };
            this.RenderTechnics = rt;
            mundo.AddCamera(cam);
            this.World = mundo;

            {
                SimpleConcreteKeyboardInputPlayable ik = new SimpleConcreteKeyboardInputPlayable(StateKey.PRESS, Keys.T, g1, EntityType.TOOLS, InputMask.G1);
                BindKeyCommand bk = new BindKeyCommand(ik, BindAction.ADD);
                CommandProcessor.getCommandProcessor().SendCommandAssyncronous(bk);
            }
            {
                SimpleConcreteKeyboardInputPlayable ik = new SimpleConcreteKeyboardInputPlayable(StateKey.PRESS, Keys.Y, g2, EntityType.TOOLS, InputMask.G2);
                BindKeyCommand bk = new BindKeyCommand(ik, BindAction.ADD);
                CommandProcessor.getCommandProcessor().SendCommandAssyncronous(bk);
            }
            
            {
                ///MASCARA SYSTEM ESTA SEMPRE LIGADA, nao quantos TurnOffs forem usados
                SimpleConcreteKeyboardInputPlayable ik = new SimpleConcreteKeyboardInputPlayable(StateKey.PRESS, Keys.Space, ChangeGroup, EntityType.TOOLS,InputMask.GSYSTEM);
                BindKeyCommand bk = new BindKeyCommand(ik, BindAction.ADD);
                CommandProcessor.getCommandProcessor().SendCommandAssyncronous(bk);
            }
            ///AO nao especificar a mascara
            ///A mascara GSYSTEM sera aplicada (sempre ativada, NAO HA COMO DESATIVA-LA USANDO O TURNOFF)
            {
                ///StateKey.DOWN eh a todo frame enquanto a tecla estiver apertada (vale o mesmo para o UP)
                ///StateKey.PRESS eh disparado uma unica vez ao pressionar uma tecla (vale o mesmo para o RELEASE)
                ///Com combo, melhor utilizar o DOWN para capturar o evento
                ///O CAMPO EntityType eh utilizado apenas para fins estatisticos
                ///O BindKeyCommand serve para cadastrar o KeyboardInputPlayable (pode-se descadastrar um KeyboardInputPlayable -- a funcao callback nao sera mais chamada)
                SimpleConcreteKeyboardInputPlayable ik = new SimpleConcreteKeyboardInputPlayable(StateKey.DOWN, new Keys[] { Keys.LeftControl, Keys.U }, Multiple, EntityType.TOOLS);
                BindKeyCommand bk = new BindKeyCommand(ik, BindAction.ADD);
                CommandProcessor.getCommandProcessor().SendCommandAssyncronous(bk);
            }


            TurnOnInputMaskCommand tom = new TurnOnInputMaskCommand(InputMask.GALL);
            CommandProcessor.getCommandProcessor().SendCommandAssyncronous(tom);

            Drawing.Draw2dTextAt2dLocation("Group ALL Active", new Vector2(20, 40), Color.White);
            Drawing.ClearEveryFrame = false;
        }

        public void g1(InputPlayableKeyBoard ipk)
        {
            Drawing.Draw2dTextAt2dLocation("Group1", new Vector2(20, 20), Color.White);
        }
        public void g2(InputPlayableKeyBoard ipk)
        {
            Drawing.Draw2dTextAt2dLocation("Group2", new Vector2(100, 20), Color.White);
        }

        InputMask[] Im = new InputMask[] { InputMask.G1, InputMask.G2, InputMask.GALL };
        string[] Groups = new string[] { "G1", "G2", "GALL" };
        int index = 2;
        public void ChangeGroup(InputPlayableKeyBoard ipk)
        {
            index = (index + 1) % 3;

            ///Inicialmente desligar TODAS as mascaras
            TurnOffInputMaskCommand tof = new TurnOffInputMaskCommand(InputMask.GALL);
            CommandProcessor.getCommandProcessor().SendCommandAssyncronous(tof);

            ///Ligar apenas a mascara correta
            ///As mascaras sao campos Bit Field, sendo possivel realizar operacoes como InputMask.GALL | InputMask.G1
            ///O TurnOnInputMaskCommand apenas combina a mascara atual com a mandada no parametro, ELE NAO DESATIVA AS QUE JA ESTIVEREM ATIVAS (porisso q foi mandado um turnoff antes)
            TurnOnInputMaskCommand tom = new TurnOnInputMaskCommand(Im[index] | InputMask.GNONE);            
            CommandProcessor.getCommandProcessor().SendCommandAssyncronous(tom);

            Drawing.ClearAll();
            Drawing.Draw2dTextAt2dLocation("ChangeGroup " + Groups[index], new Vector2(20, 40), Color.White);
        }

        public void Multiple(InputPlayableKeyBoard ipk)
        {
            Drawing.Draw2dTextAt2dLocation("Combo Pressed", new Vector2(20, 60), Color.White);
        }
        
    }
}

